package com.topisv.tms.service.lpn;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.costants.StorageConstants;
import com.topisv.tms.entity.lpn.StorageOrder;
import com.topisv.tms.entity.lpn.VPalletInfo;
import com.topisv.tms.entity.lpn.VPalletOrder;
import com.topisv.tms.repository.lpn.StorageOrderDao;
import com.topisv.tms.repository.lpn.VPalletInfoDao;
import com.topisv.tms.repository.lpn.VPalletOrderDao;
import com.topisv.tms.service.base.BaseService;
import com.topisv.tms.web.lpn.vo.PalletInfoVo;
import com.topisv.tms.web.lpn.vo.PalletOrderVo;

@Component
@Transactional(readOnly = true)
public class StorageOrderService extends BaseService {
    
    @Autowired
    private StorageOrderDao storageOrderDao;
    
    @Autowired
    private VPalletOrderDao vPalletOrderDao;
    
    @Autowired
    private VPalletInfoDao vPalletInfoDao ;
    
    @Autowired
    private PalletService palletService;
    
    /**
     * 根据lpn和绑定状态获取绑定的订单
     * 
     * @param lpn
     * @param status
     * @return [参数说明]
     * 
     * @return List<StorageOrder> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public List<StorageOrder> getStorageOrderByLpn(String lpn, int status) {
        return StringUtils.isEmpty(lpn) ? null : storageOrderDao.getStorageOrderByLpn(lpn, status);
    }
    
    /**
     * 根据lpn获取绑定的订单
     * 
     * @param lpn
     * @return [参数说明]
     * 
     * @return List<StorageOrder> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public List<StorageOrder> getStorageOrderByLpn(String lpn) {
        return StringUtils.isEmpty(lpn) ? null : storageOrderDao.getStorageOrderByLpn(lpn);
    }
    
    public int getMaxBatchSeqByLpn(String lpn) {
        Integer val = storageOrderDao.getMaxBatchSeqByLpn(lpn);
        return null == val ? 0 : val;
    }
    
    /**
     * 检测订单是否已装箱 true:已绑定 false： 未绑定
     * 
     * @return [参数说明]
     * 
     * @return boolean [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public boolean checkOrderIsBind(String orderNo) {
        return null == storageOrderDao.getStorageOrderByOrderAndStatus(orderNo,
            StorageConstants.StorageOrder.STATUS_LOADED) ? false : true;
    }
    
    /**
     * 裝箱操在
     * 
     * @param id
     * @param palletOrders
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    @Transactional
    public int loadedBatchPalletById(long id, List<StorageOrder> palletOrders) {
        if (palletService.updToUseById(id) == 1) {
            Iterable<StorageOrder> iter = storageOrderDao.save(palletOrders);
            int total = 0;
            for (StorageOrder storageOrder : iter) {
                if (null != storageOrder) {
                    total++;
                }
            }
            return total;
        } else {
            return StorageConstants.OPE_FAIL_PALLET_IS_USE;
        }
    }
    
    /**
     * 裝箱操在
     * 
     * @param lpn
     * @param palletOrders
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    @Transactional
    public int loadedBatchPalletByLpn(String lpn, List<StorageOrder> palletOrders) {
        if (palletService.updToUseByLpn(lpn) == 1) {
            Iterable<StorageOrder> iter = storageOrderDao.save(palletOrders);
            int total = 0;
            for (StorageOrder storageOrder : iter) {
                if (null != storageOrder) {
                    total++;
                }
            }
            return total;
        } else {
            return StorageConstants.OPE_FAIL_PALLET_IS_USE;
        }
    }
    
    /**
     * 分页查询
     * 
     * @param palletOrderVo
     * @param page
     * @return [参数说明]
     * 
     * @return Page<VPalletOrder> [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public Page<VPalletOrder> findAll(PalletOrderVo palletOrderVo, PageRequest page) {
        Specification<VPalletOrder> spec = expWhereVo(null == palletOrderVo ? new PalletOrderVo() : palletOrderVo);
        page = null == page ? new PageRequest(1, 10) : page;
        return vPalletOrderDao.findAll(spec,
            buildPageRequest(page.getPageNumber(), page.getPageSize(), page.getSort().toString()));
    }
    
    public List<PalletOrderVo> finAll(PalletOrderVo palletOrderVo) {
        List<PalletOrderVo> voList = null;
        if (null != palletOrderVo) {
            List<VPalletOrder> pallets = null;
            Specification<VPalletOrder> spec = expWhereVo(palletOrderVo);
            if (null == palletOrderVo.getPage()) {
                pallets = vPalletOrderDao.findAll(spec);
            } else {
                PageRequest page = palletOrderVo.getPage();
                pallets = vPalletOrderDao
                    .findAll(spec,
                        buildPageRequest(page.getPageNumber(), page.getPageSize(), page.getSort().toString()))
                    .getContent();
            }
            if (null != pallets) {
                voList = new ArrayList<PalletOrderVo>(pallets.size());
                for (VPalletOrder pallet : pallets) {
                    voList.add(entityToVo(pallet));
                }
            }
        }
        return voList;
    }
    public List<PalletInfoVo> finAll2(PalletInfoVo palletInfoVo) {
        List<PalletInfoVo> voList = null;
        if (null != palletInfoVo) {
            List<VPalletInfo> pallets = null;
            Specification<VPalletInfo> spec = expWhereVo2(palletInfoVo);
            if (null == palletInfoVo.getPage()) {
            	pallets = vPalletInfoDao.findAll(spec);
            } else {
                PageRequest page = palletInfoVo.getPage();
                pallets = vPalletInfoDao
                    .findAll(spec,
                        buildPageRequest(page.getPageNumber(), page.getPageSize(), page.getSort().toString()))
                    .getContent();
            }
            if (null != pallets) {
                voList = new ArrayList<PalletInfoVo>(pallets.size());
                for (VPalletInfo pallet : pallets) {
                    voList.add(entityToVo2(pallet));
                }
            }
        }
        return voList;
    }
    
    /**
     * 根据LPN修改状态
     * 
     * @param status
     * @param lpnNos
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int modifyStatusByLpnNos(int status, List<String> lpnNos) {
    	for(String lpnNo:lpnNos){
    		if(null!=storageOrderDao.getMaxBatchSeqByLpn(lpnNo)){
    			storageOrderDao.modifyStatusByLpnNoAndBatch(status, lpnNo,storageOrderDao.getMaxBatchSeqByLpn(lpnNo)) ;
    		}
    	}
        return 1;
    }
    
    /**
     * 根据LPN修改状态
     * 
     * @param status
     * @param lpnNo
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int modifyStatusByLpnNos(int status, String lpnNo) {
        return storageOrderDao.modifyStatusByLpnNos(status, lpnNo);
    }
    
    /**
     * 根据订单号修改状态
     * 
     * @param status
     * @param orderNos
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int modifyStatusByOrderNos(int status, List<String> orderNos) {
        return storageOrderDao.modifyStatusByOrderNos(status, orderNos);
    }
    
    /**
     * 根据订单号修改状态
     * 
     * @param status
     * @param orderNo
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int modifyStatusByOrderNos(int status, String orderNo) {
        return storageOrderDao.modifyStatusByOrderNos(status, orderNo);
    }
    
    /**
     * 根据状态和lpn修改容器与订单的绑定状态
     * 
     * @param status
     *            修改后的状态
     * @param oldStatus
     *            修改前的状态
     * @param lpnNos
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int modifyStatusByLpnNos(int status, int oldStatus, List<String> lpnNos) {
        return storageOrderDao.modifyStatusByLpnNos(status, oldStatus, lpnNos);
    }
    
    /**
     * 根据状态和lpn修改容器与订单的绑定状态
     * 
     * @param status
     *            修改后的状态
     * @param oldStatus
     *            修改前的状态
     * @param lpnNo
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int modifyStatusByLpnNos(int status, int oldStatus, String lpnNo) {
        return storageOrderDao.modifyStatusByLpnNos(status, oldStatus, lpnNo);
    }
    
    /**
     * 根据lpn卸载托盘与顶的绑定关系
     * 
     * @param lpns
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int unloadOrdersByLpnNos(List<String> lpns) {
        return modifyStatusByLpnNos(StorageConstants.StorageOrder.STATUS_UNLOAD,
            StorageConstants.StorageOrder.STATUS_LOADED,
            lpns);
    }
    
    /**
     * 根据lpn卸载托盘与顶的绑定关系
     * 
     * @param lpns
     * @return [参数说明]
     * 
     * @return int [返回类型说明]
     * @exception throws [违例类型] [违例说明]
     * @see [类、类#方法、类#成员]
     */
    public int unloadOrdersByLpnNos(String lpn) {
        return modifyStatusByLpnNos(StorageConstants.StorageOrder.STATUS_UNLOAD,
            StorageConstants.StorageOrder.STATUS_LOADED,
            lpn);
    }
    
    private PalletOrderVo entityToVo(VPalletOrder pallet) {
        PalletOrderVo vo = null;
        if (null != pallet) {
            vo = new PalletOrderVo();
            vo.setBatchSeq(pallet.getBatchSeq());
            vo.setCreateTime(pallet.getCreateTime());
            vo.setId(pallet.getId());
            vo.setIsValid(pallet.getIsValid());
            if (StorageConstants.StorageOrder.STATUS_UNLOAD  == pallet.getStatus()){
                vo.setLast_update_time(pallet.getUpdateTime());
            }
            vo.setLpnNo(pallet.getLpnNo());
            vo.setName(pallet.getName());
            vo.setOrderNo(pallet.getOrderNo());
            vo.setPalletNum(pallet.getPalletNum());
            vo.setRemark(pallet.getRemark());
            vo.setStatus(pallet.getStatus());
            vo.setStorageId(pallet.getStorageId());
            vo.setWarehouseCode(pallet.getWarehouseCode());
        }
        return vo;
    }
    private PalletInfoVo entityToVo2(VPalletInfo pallet) {
    	PalletInfoVo vo = null;
        if (null != pallet) {
            vo = new PalletInfoVo();
            vo.setBatchSeq(pallet.getBatchSeq());
            vo.setCreateTime(pallet.getCreateTime());
            if (StorageConstants.StorageOrder.STATUS_UNLOAD  == pallet.getStatus()){
                vo.setLast_update_time(pallet.getUpdateTime());
            }
            vo.setLpnNo(pallet.getLpnNo());
            vo.setName(pallet.getName());
            vo.setOrderNo(pallet.getOrderNo());
            vo.setPalletNum(pallet.getPalletNum());
            vo.setStatus(pallet.getStatus());
            vo.setWarehouseCode(pallet.getWarehouseCode());
            vo.setNam(pallet.getNam());
            vo.setQty(pallet.getQty());
            vo.setSkuId(pallet.getSkuId());
        }
        return vo;
    }
    
    /**
     * 查询条件封装
     * 
     * @param vo
     * @return
     */
    private Specification<VPalletOrder> expWhereVo(final PalletOrderVo vo) {
        
        return new Specification<VPalletOrder>() {
            @Override
            public Predicate toPredicate(Root<VPalletOrder> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
                Predicate pre = cb.conjunction();
                List<Expression<Boolean>> expression = pre.getExpressions();
                String customerCode = vo.getCustomerCode();
                if (StringUtils.isNotBlank(customerCode)) {
                    expression.add(cb.like(r.get("customerCode").as(String.class), customerCode.trim()));
                }
                String warehouseCode = vo.getWarehouseCode();
                if (StringUtils.isNotBlank(warehouseCode)) {
                    expression.add(cb.like(r.get("warehouseCode").as(String.class), warehouseCode.trim()));
                }
                String orderNo = vo.getOrderNo();
                if (StringUtils.isNotBlank(orderNo)) {
                    expression.add(cb.like(r.get("orderNo").as(String.class), orderNo.trim()));
                }
                String lpnNo = vo.getLpnNo();
                if (StringUtils.isNotBlank(lpnNo)) {
                    expression.add(cb.like(r.get("lpnNo").as(String.class), lpnNo.trim()));
                }
                int batchSeq = vo.getBatchSeq();
                if (batchSeq > 0) {
                    expression.add(cb.equal(r.get("batchSeq").as(Integer.class), batchSeq));
                }
                int status = vo.getStatus();
                if (status >= 0) {
                    expression.add(cb.equal(r.get("status"), status));
                }
                int isValid = vo.getIsValid();
                if (isValid >= 0) {
                    expression.add(cb.equal(r.get("isValid"), isValid));
                }
                int storageId = vo.getStorageId();
                if (storageId > 0) {
                    expression.add(cb.equal(r.get("storageId"), storageId));
                }
                Date fromDate = vo.getStartTime();
                if (fromDate != null) {
                    expression.add(cb.greaterThanOrEqualTo(r.get("createTime").as(Date.class), fromDate));
                }
                Date toDate = vo.getEndTime();
                if (toDate != null) {
                    expression.add(cb.lessThanOrEqualTo(r.get("createTime").as(Date.class), toDate));
                }
                return pre;
            }
        };
    }
    /**
     * 查询条件封装  导出使用
     * 
     * @param vo
     * @return
     */
    private Specification<VPalletInfo> expWhereVo2(final PalletInfoVo vi) {
        
        return new Specification<VPalletInfo>() {
            @Override
            public Predicate toPredicate(Root<VPalletInfo> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
                Predicate pre = cb.conjunction();
                List<Expression<Boolean>> expression = pre.getExpressions();
                String warehouseCode = vi.getWarehouseCode();
                if (StringUtils.isNotBlank(warehouseCode)) {
                    expression.add(cb.like(r.get("warehouseCode").as(String.class), warehouseCode.trim()));
                }
                String orderNo = vi.getOrderNo();
                if (StringUtils.isNotBlank(orderNo)) {
                    expression.add(cb.like(r.get("orderNo").as(String.class), orderNo.trim()));
                }
                String lpnNo = vi.getLpnNo();
                if (StringUtils.isNotBlank(lpnNo)) {
                    expression.add(cb.like(r.get("lpnNo").as(String.class), lpnNo.trim()));
                }
                int batchSeq = vi.getBatchSeq();
                if (batchSeq > 0) {
                    expression.add(cb.equal(r.get("batchSeq").as(Integer.class), batchSeq));
                }
                int status = vi.getStatus();
                if (status >= 0) {
                    expression.add(cb.equal(r.get("status"), status));
                }
                Date fromDate = vi.getStartTime();
                if (fromDate != null) {
                    expression.add(cb.greaterThanOrEqualTo(r.get("createTime").as(Date.class), fromDate));
                }
                Date toDate = vi.getEndTime();
                if (toDate != null) {
                    expression.add(cb.lessThanOrEqualTo(r.get("createTime").as(Date.class), toDate));
                }
                return pre;
            }
        };
    }
    
    public List<StorageOrder> getStorageOrderByLpnAndOrderNo(String lpnNo,String OrderNo){
    	return storageOrderDao.getStorageOrderByLpnAndOrderNo(lpnNo, OrderNo) ; 
    }
    
}
